package Stream;

import java.util.*;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamDemo3 {
    public static void main(String[] args) {
        /*
            Stream<T>filter()          过滤
            Stream<T>limit(long maxsize)  获取前几个元素
            Stream<T>skip(long n)        跳过前几个元素
            Stream<T>distinct()       元素去重，依赖（hashCode和equals方法）
            static<T>Stream<T>concat(Stream a,Stream b)合并a和b两个流为一个流
            Stream<R>map(Function<T,R>mapper)   转换流中的数据类型
            注意一：中间方法，返回新的Stream流，原来的Stream流中能使用一次，建议使用链式编程
            注意二：修改Stream流中的数据，不会影响原来的数据
         */
        ArrayList<String> list1=new ArrayList<>();
        list1.add("张无忌-1");
        list1.add("周芷若-2");
        list1.add("张三丰-3");
        list1.add("赵敏-4");
        list1.add("张三-5");
        list1.add("黄蓉-6");
        list1.add("张三-7");

        System.out.println(list1);
        /*
        Stream流只能使用一次
        Stream<String> stream = list1.stream();
        Stream<String> stringStream = stream.filter(s -> s.length() == 3);
        stream.filter();------>此时再次调用stream会报错，因为stream已经改变为stringStream，
        无法再次使用stream这个对象

         */
        System.out.println("-------------------filter--------------");
        list1.stream().filter(name->name.startsWith("张")).filter(name->name.length()==3).forEach(name-> System.out.println(name));
        System.out.println("-------------------limit--------------");
        list1.stream().limit(3).forEach(s-> System.out.println(s));//张无忌 周芷若 张三丰
        System.out.println("-------------------skip--------------");
        list1.stream().skip(3).forEach(s-> System.out.println(s));//赵敏 张三  黄蓉
        System.out.println("-------------------distinct--------------");
        list1.stream().distinct().forEach(s-> System.out.println(s));
        System.out.println("-------------------concat--------------");
        ArrayList<String> list2=new ArrayList<>();
        Collections.addAll(list2,"郭靖","小龙女");
        Stream.concat(list1.stream(),list2.stream()).forEach(s-> System.out.println(s));
        System.out.println("-------------------Stream<R>map(Function<T,R>mapper)--------------");

        list1.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
//                通过“-”将每一个元素分为两部分，姓名为0索引，数字为1索引
                String[] arr=s.split("-");
                String ageString=arr[1];
                int age = Integer.parseInt(ageString);
                return age;
            }
        }).forEach(s-> System.out.println(s));
        /*
        void foreach           遍历
        long count             统计
        toArray                收集流中的数据，放到数组中
        collect                收集流中的数据，放到集合中
         */
        System.out.println("----------------foreach------------------");
        list1.stream().forEach(s-> System.out.println(s));
        System.out.println("----------------count------------------");
        System.out.println(list1.stream().count());
        System.out.println("----------------toArray------------------");
//        在这里list1.stream().toArray()代表着是一个对象，那么获取的是地址值
        System.out.println(list1.stream().toArray());//[Ljava.lang.Object;@4e50df2e
//        正确操作
        Object[] array = list1.stream().toArray();
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(list1.stream().toArray()));
//      指定类型  IntFunction函数式类型，需要new IntFunction操作
//        IntFunction泛型：具体类型的数组
//        apply的形参：流中数据的个数，要跟数据保持一致
//        apply的返回值：具体类型的数组
//        toArray方法的参数的作用：负责创建一个指定类型的数组
//        toArray方法的底层，会一次得到流中的每一个数据，并把数据放到数组当中
//        toArray方法的返回值：是一个装着流里所有数据的数组
        String[] array1 = list1.stream().toArray(new IntFunction<String[]>() {
            @Override
            public String[] apply(int value) {
                return new String[value];
            }
        });
        System.out.println(Arrays.toString(array1));
        System.out.println("--------------------collect--------------------");
ArrayList<String>list3=new ArrayList<>();
Collections.addAll(list3, "张无忌-男-1","周芷若-女-2",
        "张三丰-男-3","赵敏-女-4","张三-男-5","黄蓉-女-6","张三-女-7");
//s代表着流水线上的每一个数据，
        Stream<String> boy = list3.stream().filter(s -> s.split("-")[1].startsWith("男"));
        List<String> collect = boy.collect(Collectors.toList());
        System.out.println(collect);
        //        boy.forEach(s-> System.out.println(s));
//        收集到set集合
        Set<String> collect1 = list3.stream().filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toSet());
//        System.out.println(collect1);
//   收集到map集合
        list3.stream().filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toMap(new Function<String, String>() {
                    /*
                    toMap:参数一：表示键的生成规则
                          参数二：表示值的生成规则
                     参数一：Function：泛型一：表示流中每一个数据的类型
                                     泛型二：表示Map集合中键的数据类型
                            方法体apply形参：依次表示流中的每一个数据
                            方法体：生成键的代码    张无忌-男-1
                                   返回值： 已经生成的键
                     参数二：泛型一：表示流中每一个数据的类型
                           泛型二：表示Map集合中键的数据类型

                           方法体apply形参：依次表示流中的每一个数据
                            方法体：       生成键的代码    张无忌-男-1
                            返回值：       已经生成的键


                            toMap(键的规则，值的规则),所以需要进行两次的匿名函数Function，依次返回键的类型和值的类型
                     */
                                              @Override
                                              public String apply(String s) {
                                                  return s.split("-")[0];
                                              }
                                          },
                        new Function<String, Integer>() {
                    @Override
                            public Integer apply(String s){
                        return Integer.parseInt(s.split("-")[2]);
                    }
                        }
                ));
    }
}
